package main

import "fmt"

type ProcessData struct {
	arriveTime int     // 到达时间
	workTime   int     // 工作时间
	finishTime int     // 完成时间
	turnTime   int     // 周转时间
	powerTime  float64 //带权周转时间
}

var (
	avgTotalTime = 0.0
	avgPowerTime = 0.0
)

func main() {
	// 定义四个作业
	processDatas := make([]ProcessData, 4)
	processDatas[0] = ProcessData{
		arriveTime: 0,
		workTime:   20,
	}
	processDatas[1] = ProcessData{
		arriveTime: 5,
		workTime:   15,
	}
	processDatas[2] = ProcessData{
		arriveTime: 10,
		workTime:   5,
	}
	processDatas[3] = ProcessData{
		arriveTime: 15,
		workTime:   10,
	}
	// 执行短作业算法
	SJF(processDatas)
}

func SJF(processDatas []ProcessData) {
	// 前一个作业完成时间(下一个作业开始时间)
	preFinished := 0
	// 定义作业号
	number := 0
	// 比较作业完成时间与工作时间
	for i := range processDatas {
		// 最小时间
		min := 1 << 20
		if processDatas[i].workTime > min {
			panic("作业超时")
		}
		// 1.完成时间为零表示还没进行作业
		// 2.如果服务时间小于最小时间
		// 3.到达时间小于前一个作业完成时间
		for j := range processDatas {
			if processDatas[j].finishTime == 0 &&
				processDatas[j].workTime < min &&
				processDatas[j].arriveTime < preFinished {
				min = processDatas[j].workTime
				number = j
			}
		}

		// 当前作业完成时间等于前一个作业完成时间加当前作业工作时间
		processDatas[number].finishTime = preFinished + processDatas[number].workTime
		// 更新完成时间
		preFinished = processDatas[number].finishTime
		// 周转时间等于完成时间减去到达时间
		processDatas[number].turnTime = processDatas[number].finishTime -
			processDatas[number].arriveTime
		// 计算带权周转时间
		processDatas[number].powerTime = float64(processDatas[number].turnTime) /
			float64(processDatas[number].workTime)
	}
	fmt.Println("短进程优先算法: ")
	Display(processDatas)
}

// 展示进程数据
func Display(processDatas []ProcessData) {
	fmt.Printf("%-6s%-6s%-6s%-6s%-8s\n",
		"到达时间",
		"工作时间",
		"完成时间",
		"周转时间",
		"带权周转时间",
	)
	totalSum := 0.0
	powerSum := 0.0
	for _, p := range processDatas {
		fmt.Println(p)
		totalSum += float64(p.turnTime)
		powerSum += p.powerTime
	}
	avgTotalTime = totalSum / float64(len(processDatas))
	avgPowerTime = powerSum / float64(len(processDatas))

	fmt.Println("平均周转时间:", avgTotalTime)
	fmt.Println("平均带权周转时间:", avgPowerTime)
}

// 格式化作业数据
func (p ProcessData) String() string {
	return fmt.Sprintf("%-10d%-10d%-10d%-10d%-14.2f",
		p.arriveTime,
		p.workTime,
		p.finishTime,
		p.turnTime,
		p.powerTime,
	)
}
